package com.shxy.rlzy.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.shxy.rlzy.entity.*;
import com.shxy.rlzy.mapper.*;
import com.shxy.rlzy.service.IAuthoritySerivce;
import com.shxy.rlzy.service.IRoleMenuService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shxy.rlzy.utils.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author tanhao
 * @since 2021-08-16
 */
@Service
public class RoleMenuServiceImpl extends ServiceImpl<RoleMenuMapper, RoleMenu> implements IRoleMenuService {
    private UserMapper userMapper;
    private RoleMapper roleMapper;
    private MenuMapper menuMapper;
    private RoleMenuMapper roleMenuMapper;
    private RedisUtil redisUtil;
    private IAuthoritySerivce authoritySerivce;

    @Autowired
    public void setMenuMapper(MenuMapper menuMapper) {
        this.menuMapper = menuMapper;
    }
    @Autowired
    public void setRoleMenuMapper(RoleMenuMapper roleMenuMapper) {
        this.roleMenuMapper = roleMenuMapper;
    }
    @Autowired
    public void setRoleMapper(RoleMapper roleMapper) {
        this.roleMapper = roleMapper;
    }
    @Autowired
    public void setUserMapper(UserMapper userMapper) {
        this.userMapper = userMapper;
    }
    @Autowired
    public void setRedisUtil(RedisUtil redisUtil) {
        this.redisUtil = redisUtil;
    }
    @Autowired
    public void setAuthoritySerivce(IAuthoritySerivce authoritySerivce) { this.authoritySerivce = authoritySerivce; }

    @Override
    public void initRoleMenus() {
        // 获取所有菜单id
        List<Long> menuIds = menuMapper.selectList(new QueryWrapper<>()).stream().map(Menu::getId).toList();
        // 获取所有角色
        List<Role> roles = roleMapper.selectList(new QueryWrapper<>());
        // 初始化每个角色的菜单
        roles.forEach(role -> {
            List<Long> rmids = roleMenuMapper.listByRoleId(role.getId()).stream().map(RoleMenu::getMenuId).toList();
            List<RoleMenu> roleMenus = menuIds.stream().filter(mid -> rmids.stream().noneMatch(rmid -> rmid == mid)) // 过滤无法访问的菜单id
                    // 构建角色菜单项目
                    .map(mid -> {
                        RoleMenu roleMenu = new RoleMenu();
                        roleMenu.setRoleId(role.getId());
                        roleMenu.setMenuId(mid);
                        roleMenu.setEnable(false);
                        return roleMenu;
                    }).toList();
            // 批量保存角色菜单
            this.saveBatch(roleMenus);
        });
    }

    @Override
    public List<RoleMenu> initRoleMenus(Long roleId) {
        // 查询不存在的菜单编号
        List<Long> menuIds = menuMapper.getNotRoleMenuIds(roleId);
        List<RoleMenu> roleMenus = menuIds.stream().map(mid -> {
            RoleMenu roleMenu = new RoleMenu();
            roleMenu.setRoleId(roleId);
            roleMenu.setMenuId(mid);
            roleMenu.setEnable(false);
            return roleMenu;
        }).toList();
        if(roleMenus.size() > 0) {
            this.saveBatch(roleMenus);
        }

        return this.list(new QueryWrapper<RoleMenu>().eq("role_id", roleId));
    }

    @Override
    @Transactional
    public void setRoleMenus(Long roleId, List<Long> menuIds) {
        // 初始化角色菜单项，并获取全部菜单信息
        List<RoleMenu> roleMenus = initRoleMenus(roleId);
        // 设置角色访问权限
        roleMenus.forEach(roleMenu -> {
            roleMenu.setEnable(menuIds.contains(roleMenu.getMenuId()));
        });
        // 保存设置
        this.updateBatchById(roleMenus);
        // 刷新权限缓存
        refreshRoleAuthorities(roleId);
    }

    @Override
    public List<RoleMenu> listByRoleId(Long roleId) {
        return roleMenuMapper.listByRoleId(roleId);
    }

    @Override
    public void refreshRoleAuthorities(Long roleId) {
        // 查询指定角色的用户列表
        List<User> users = userMapper.getUsersOfRole(roleId);
        // 构造redis键
        users.forEach(user -> {
            Long userId = user.getId();
            String redisKey = "GrantedAuthority:" + user.getUsername(); // 构造redis键
            // 获取用户权限
            String authorities = authoritySerivce.getAuthoritiesByUserId(userId);
            // 将用户权限保存到redis中
            redisUtil.set(redisKey, authorities, 60 * 60);
        });
    }

    @Override
    public boolean deleteByRole(Long roleId) {
        QueryWrapper<RoleMenu> qw = new QueryWrapper<>();
        qw.eq("role_id", roleId);
        return remove(qw);
    }

    @Override
    public boolean deleteByMenu(Long menuId) {
        QueryWrapper<RoleMenu> qw = new QueryWrapper<>();
        qw.eq("menu_id", menuId);
        return remove(qw);
    }

    @Override
    public boolean deleteByRoleMenu(Long roleId, Long menuId) {
        QueryWrapper<RoleMenu> qw = new QueryWrapper<>();
        qw.eq("role_id", roleId);
        qw.eq("menu_id", menuId);
        return remove(qw);
    }
}
